using IQIGame.Onigao.Framework;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor.Callbacks;

namespace IQIGame.Onigao.GamePlay.Editors
{
    public static class EntityGenBindingEnumGen
    {
        private static HashSet<string> _attrNames = new HashSet<string>();
        private static Dictionary<string, Type> _attrNameTypeMap = new Dictionary<string, Type>();
        private static List<string> _tempNameList = new List<string>();
        private static EditorPreferenceString _curNamesPrefs = new EditorPreferenceString(PlayerPrefsConst.EditorEntityGenBindingEnumNames, string.Empty);

        private static string codeDir = UnityEngine.Application.dataPath + "/Scripts/GamePlay/Editor/ArtTools/ArtCommon/Config";
        private static string enumClassText =
@"namespace IQIGame.Onigao.GamePlay.Editors
{
    public enum EntityGenBindingComponentType
    {
        None = 0,
$Names
    }

    public static class EntityGenBindingComTypeBook
    {
        public static System.Type SearchType(EntityGenBindingComponentType type)
        {
            switch (type)
            {
$SwitchBlocks
                default:
                    return null;
            }
        }
    }
}";

        [DidReloadScripts]
        private static void OnScriptsReloaded()
        {
            //UnityEngine.Debug.LogWarning("开始尝试重新生成Enum");

            GetAllEntityGenAttributeNames(_tempNameList);

            string json = _curNamesPrefs.Value;
            List<string> curNames = null;
            if (!string.IsNullOrEmpty(json))
            {
                curNames = JsonConvert.DeserializeObject<List<string>>(json);
            }
            //UnityEngine.Debug.LogWarning(curNames == null ? "Null" : string.Join(",", curNames));
            //UnityEngine.Debug.LogWarning(string.Join(",", _tempNameList));

            bool isChanged = curNames == null || curNames.Count != _tempNameList.Count;
            if (!isChanged)
            {
                for (int i = 0; i < curNames.Count; i++)
                {
                    if (curNames[i] != _tempNameList[i])
                    {
                        isChanged = true;
                        break;
                    }
                }
            }

            if (!isChanged)
            {
                return;
            }

            _curNamesPrefs.Value = JsonConvert.SerializeObject(_tempNameList);
            //UnityEngine.Debug.LogWarning("真的开始尝试重新生成Enum");
            GenerateEnum(_tempNameList);
        }

        private static void GetAllEntityGenAttributeNames(List<string> nameList)
        {
            _attrNames.Clear();
            _attrNameTypeMap.Clear();
            nameList.Clear();
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assembly in assemblies)
            {
                var types = assembly.GetTypes();
                foreach (var type in types)
                {
                    var attr = type.GetCustomAttribute<EntityGenPrebindAttribute>();
                    if (attr != null)
                    {
                        if (_attrNames.Add(attr.Name))
                        {
                            _attrNameTypeMap.Add(attr.Name, type);
                        }
                    }
                }
            }

            foreach (var item in _attrNames)
            {
                nameList.Add(item);
            }

            nameList.Sort();
        }

        private static void GenerateEnum(List<string> names)
        {
            string namesContent = string.Empty;
            string typeContent = string.Empty;
            for (int i = 0; i < names.Count; i++)
            {
                string name = names[i];
                Type type = _attrNameTypeMap[name];
                namesContent += $"        {name} = {i + 1},\n";
                typeContent += @$"                case EntityGenBindingComponentType.{name}:
                    return typeof({type.Name});";
            }
            string enumCode = enumClassText.Replace("$Names", namesContent);
            enumCode = enumCode.Replace("$SwitchBlocks", typeContent);
            if (!Directory.Exists(codeDir))
            {
                Directory.CreateDirectory(codeDir);
            }
            File.WriteAllText(codeDir + "/EntityGenBindingComponentType.cs", enumCode);
        }
    }
}
